using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using DMTT.Workflow.Activities;

namespace DMTT.Workflow.Activities.Design
{
    public partial class MappingForm : Form
    {
        private IMapProperties m_activity;
        private Type m_sourceType;
        private Type m_destinationType;
        
        public MappingForm(IMapProperties activity)
        {
            InitializeComponent();
            
            m_activity = activity;
            m_sourceType = activity.SourceType;
            m_destinationType = activity.DestinationType;

            this.FillTreeView(this.sourceTreeView, null, m_sourceType);
            this.FillTreeView(this.destinationTreeView, null, m_destinationType);
            this.mappingPanel.Invalidate();

            this.sourceListView.Columns[0].Text = m_sourceType.Name;
            this.destinationListView.Columns[0].Text = m_destinationType.Name;

            MappingCollection mappings = (MappingCollection)activity.Mappings;
            foreach (Mapping map in mappings)
            {
                TreeNode sourceNode = null;
                TreeNode destNode = null;
                TreeNode[] sourceNodes = this.sourceTreeView.Nodes.Find(map.From, true);
                if (sourceNodes.Length > 0)
                {
                    sourceNode = sourceNodes[0];
                }
                TreeNode[] destNodes = this.destinationTreeView.Nodes.Find(map.To, true);
                if (destNodes.Length > 0)
                {
                    destNode = destNodes[0];
                }
                if (sourceNode != null && destNode != null)
                {
                    this.mappingPanel.ConnectionDrawingService.AddLinkItem(sourceNode, destNode);
                }
            }
            this.mappingPanel.Invalidate();
        }

        public MappingCollection GetMappings()
        {
            MappingCollection mappings = new MappingCollection();
            foreach (TreeViewLinkItem item in this.mappingPanel.ConnectionDrawingService.TreeViewLinkItems)
            {
                Mapping map = new Mapping();
                map.From = this.CreateName(item.SourceNode);
                map.To = this.CreateName(item.DestinationNode);
                mappings.Add(map);
            }
            return mappings;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            if (e.KeyCode == Keys.Delete)
            {
                this.mappingPanel.LinkItems.Remove(this.mappingPanel.SelectedItem);
                this.mappingPanel.SelectedItem = null;
                this.mappingPanel.Invalidate();
            }
        }

        private void FillTreeView(TreeView tree, TreeNode parentNode, Type type)
        {
            PropertyInfo[] propInfos = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            TreeNode node = null;
            foreach (PropertyInfo propInfo in propInfos)
            {
                if (parentNode == null)
                {
                    node = tree.Nodes.Add(propInfo.Name, propInfo.Name, 0);
                }
                else
                {
                    string name = this.CreateName(parentNode) + "." + propInfo.Name;
                    node = parentNode.Nodes.Add(name, propInfo.Name, 0);
                }
                node.Tag = this.CreateName(node);
                node.Expand();

                if (propInfo.PropertyType != typeof(string))
                {
                    this.FillTreeView(tree, node, propInfo.PropertyType);
                }
            }

            FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
            foreach (FieldInfo fieldInfo in fieldInfos)
            {
                if (parentNode == null)
                {
                    node = tree.Nodes.Add(fieldInfo.Name, fieldInfo.Name, 0);
                }
                else
                {
                    string name = this.CreateName(parentNode) + "." + fieldInfo.Name;
                    node = parentNode.Nodes.Add(name, fieldInfo.Name, 0);
                }
                node.Tag = this.CreateName(node);
                node.Expand();

                if (fieldInfo.FieldType != typeof(string))
                {
                    this.FillTreeView(tree, node, fieldInfo.FieldType);
                }
            }
        }

        private string CreateName(TreeNode node)
        {
            string name = node.Text;
            while (node.Parent != null)
            {
                name = node.Parent.Text + "." + name;
                node = node.Parent;
            }
            return name;
        }

        private void mappingPanel_BeforeTreeViewLinkCreation(object sender, BeforeTreeViewLinkCreationEventArgs e)
        {
            Mapping map = new Mapping();
            map.From = this.CreateName(e.SourceNode);
            map.To = this.CreateName(e.DestinationNode);
            if (this.m_activity.ValidateMapping(map) == false)
            {
                e.Cancel = true;
            }
            return;
        }
    }
}